#include <fstream>
#include "conv.h"
#include "deconv.h"
#include "im2col.h"
#include "utils.h"
#include "unet_v1_q_params.h"
#include "unetv1.h"
#include "concat.h"
#include "norm_actv.h"
#include "maxPool.h"
#include "add_bias.h"

template<
    unsigned W,
    unsigned B,
    unsigned QRS,
    unsigned PICH, 
    unsigned POCH, 
    unsigned PCH,
    unsigned last_PCH,//上一层的PCH
    unsigned NIH,
    unsigned NIW,
    unsigned NICH,
    unsigned NOH,
    unsigned NOW,
    unsigned NOCH,
    unsigned MAXPOOL_PMAXPL
>
void conv_transpose_kernel(data_stream<last_PCH * CONV_A_BIT> s_last_actv, data_stream<MAXPOOL_PMAXPL * CONV_A_BIT> s_maxpool)
{
    // conv1-2
     std::cout << "conv1-2" << std::endl;
    data_stream<PICH * CONV_A_BIT> s_im2col_in("s_im2col_in");
    data_stream<PICH * CONV_A_BIT> s_im2col("s_im2col");
    data_stream<POCH * CONV_B_BIT> s_conv("s_conv");
    data_stream<PCH * CONV_B_BIT> s_actv_in("s_actv_in");
    data_stream<PCH * CONV_A_BIT> s_actv("s_actv");
    data_stream<PCH * CONV_A_BIT> s_actv_copy("s_actv_copy");
    data_stream<PCH * CONV_A_BIT> s_concat1_in1("s_concat1_in1");
    data_stream<MAXPOOL1_PMAXPL * CONV_A_BIT> s_maxpool1_in("s_maxpool1_in");
    data_stream<MAXPOOL1_PMAXPL * CONV_A_BIT> s_maxpool1("s_maxpool1");
    #pragma HLS STREAM variable=s_im2col_in          depth=CONV_KH*NIW*NICH/PICH dim=1
    #pragma HLS STREAM variable=s_im2col             depth=DEFAULT_DEPTH dim=1
    #pragma HLS STREAM variable=s_conv             depth=DEFAULT_DEPTH dim=1
    #pragma HLS STREAM variable=s_actv_in     depth=DEFAULT_DEPTH dim=1
    #pragma HLS STREAM variable=s_actv        depth=DEFAULT_DEPTH dim=1
    #pragma HLS STREAM variable=s_actv_copy   depth=DEFAULT_DEPTH dim=1
    #pragma HLS STREAM variable=s_concat1_in1         depth=NOH*NOW*NOCH/PCH dim=1
    #pragma HLS STREAM variable=s_maxpool1_in         depth=DEFAULT_DEPTH dim=1
    #pragma HLS STREAM variable=s_maxpool1            depth=(NOW/2 +2) *NOCH/MAXPOOL1_PMAXPL dim=1    

    #pragma HLS RESOURCE variable=s_im2col_in        core=FIFO_BRAM
    #pragma HLS RESOURCE variable=s_im2col           core=FIFO_SRL
    #pragma HLS RESOURCE variable=s_conv           core=FIFO_SRL
    #pragma HLS RESOURCE variable=s_actv_in   core=FIFO_SRL
    #pragma HLS RESOURCE variable=s_actv      core=FIFO_SRL
    #pragma HLS RESOURCE variable=s_actv_copy core=FIFO_SRL
    #pragma HLS RESOURCE variable=s_concat1_in1       core=FIFO_BRAM
    #pragma HLS RESOURCE variable=s_maxpool1_in       core=FIFO_SRL
    #pragma HLS RESOURCE variable=s_maxpool1          core=FIFO_BRAM
    expandWidth<last_PCH * CONV_A_BIT, PICH * CONV_A_BIT,
                NIH * NIW * NICH>(s_last_actv, s_im2col_in);

     im2col_3x3<1, NIH, NIW, NICH* CONV_A_BIT, PICH* CONV_A_BIT, 0>(s_im2col_in, s_im2col);
    conv<PICH, POCH,
         NICH, NOCH, CONV_KH, CONV_A_BIT, CONV_W_BIT, CONV_B_BIT,
         NOH * NOW>(s_im2col, s_conv, W);

    reduceWidth<POCH * CONV_B_BIT, PCH * CONV_B_BIT,
                NOH * NOW * NOCH / POCH>(s_conv,
                                                                         s_actv_in);
    norm_actv<PCH, NOCH, CONV_B_BIT, CONV_M_BIT, CONV_A_BIT,
              NOH * NOW>(s_actv_in, s_actv, B, QRS);

    copy_stream<PCH * CONV_A_BIT, NOH * NOW * NOCH / PCH>(
        s_actv, s_concat1_in1, s_actv_copy);
    expandWidth<PCH * CONV_A_BIT, MAXPOOL1_PMAXPL * CONV_A_BIT,
                NOH * NOW * NOCH>(s_actv_copy, s_maxpool1_in);
    maxPool2x2<MAXPOOL1_PMAXPL, NOCH, CONV_A_BIT, NOH, NOW, 1>(
        s_maxpool1_in, s_maxpool1);
    return ;
}